package com.lyncs.ods.utils;

import cn.hutool.core.util.StrUtil;
import com.lyncs.ods.cache.CurrencyRateCache;
import com.lyncs.ods.constant.CurrencyEnum;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.Objects;
import java.util.function.BiFunction;

/**
 * @author alex
 * @date 2022/04/03 22:23
 * @description
 */
public class CurrencyUtil {

    /**
     * currency:rate:USD:CNY:20220401
     */
    public static final String CACHE_KEY = "currency:rate:{}:{}:{}";
    public static final BigDecimal HUNDRED = new BigDecimal("100");

    public static BigDecimal yuan2fen(BigDecimal amount) {
        if (Objects.isNull(amount)) {
            return BigDecimal.ZERO;
        }
        return amount.multiply(HUNDRED);
    }

    public static BigDecimal fen2yuan(BigDecimal amount) {
        if (Objects.isNull(amount)) {
            return BigDecimal.ZERO;
        }
        return amount.divide(HUNDRED, 2, RoundingMode.UP);
    }

    /**
     * 汇率转换
     *
     * @param fromCurrency 原货币
     * @param toCurrency   目标货币
     * @param amount       转换金额
     * @param need2Yuan    是否需要元转分
     * @return 计算结果
     */
    public static BigDecimal exchange(String fromCurrency, String toCurrency, BigDecimal amount, Boolean need2Yuan) {
        //fromCurrency转CNY
        BiFunction<String, BigDecimal, BigDecimal> toCnyRateFunc = (fromCurrencyCode, fromAmount) -> fromAmount.divide(getRate(fromCurrency), 4, RoundingMode.UP);
        //CNY转toCurrency
        BiFunction<String, BigDecimal, BigDecimal> fromCnyRateFunc = (toCurrencyCode, fromAmount) -> fromAmount.multiply(getRate(toCurrencyCode));
        BigDecimal calculatedRate = fromCnyRateFunc.apply(toCurrency, toCnyRateFunc.apply(fromCurrency, amount));
        if (need2Yuan) {
            return fen2yuan(calculatedRate).setScale(2, RoundingMode.UP);
        }
        return calculatedRate.setScale(2, RoundingMode.UP);
    }

    public static BigDecimal exchange(String fromCurrency, String toCurrency, BigDecimal amount) {
        return exchange(fromCurrency, toCurrency, amount, Boolean.FALSE);
    }

    public static String getCacheKey(String fromCurrency, String toCurrency) {
        return getCacheKey(fromCurrency, toCurrency, LocalDate.now());
    }

    public static String getCacheKey(String fromCurrency, String toCurrency, LocalDate date) {
        return StrUtil.format(CACHE_KEY, fromCurrency, toCurrency, date);
    }

    public static BigDecimal getRate(String fromCurrency) {
        BigDecimal rate = CurrencyRateCache.get(fromCurrency, CurrencyEnum.CNY.getCurrency());
        if (Objects.isNull(rate)) {
            rate = BigDecimal.ONE;
        }
        return rate;
    }
}
